package com.qdlc.p2p.biz.protocol;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.qdlc.p2p.dal.dto.*;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.WritableDirectElement;
import com.itextpdf.text.pdf.draw.LineSeparator;
import com.itextpdf.tool.xml.ElementHandler;
import com.itextpdf.tool.xml.Writable;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.pipeline.WritableElement;
import com.qdlc.p2p.biz.service.BorrowCollectionService;
import com.qdlc.p2p.biz.service.BorrowProtocolService;
import com.qdlc.p2p.biz.service.BorrowRepaymentService;
import com.qdlc.p2p.biz.service.BorrowService;
import com.qdlc.p2p.biz.service.BorrowTenderService;
import com.qdlc.p2p.biz.service.SystemConfigService;
import com.qdlc.p2p.biz.service.UserService;
import com.qdlc.p2p.biz.service.VerifyLogService;
import com.qdlc.p2p.biz.util.itext.PdfHelper;
import com.qdlc.p2p.common.constant.BorrowStyle;
import com.qdlc.p2p.common.exception.BorrowException;
import com.qdlc.p2p.common.util.BeanUtil;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.FreemarkerUtil;
import com.qdlc.p2p.common.util.MoneyUtil;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.dal.dao.MemberInfosDao;
import com.qdlc.p2p.dal.model.BorrowModel;
import com.qdlc.p2p.dal.model.BorrowTenderModel;
import com.qdlc.p2p.dal.util.UserUtils;

/**
 * 创建协议抽象类
 * 
 * @author qj
 * @version 2.0
 * @since 2014-05-22
 */
public abstract class AbstractProtocolBean implements ProtocolBean {
	private static Logger logger = Logger.getLogger(AbstractProtocolBean.class);

	protected BorrowService borrowService;
	protected BorrowTenderService borrowTenderService;
	protected BorrowCollectionService borrowCollectionService;
	protected VerifyLogService verifyLogService;
	protected UserService userService;
	protected BorrowProtocolService borrowProtocolService;
	protected BorrowRepaymentService borrowRepaymentService;
	protected SystemConfigService systemConfigService;
	protected MemberInfosDao memberInfosDao;

	// 生成pdf路径名
	protected String inPdfName;
	// 下载pdf名
	protected String downloadFileName;
	// 标id
	protected long borrowId;
	// 标model
	protected BorrowModel borrow;
	// 投标记录
	protected List<BorrowTenderModel> tenderList;
	// 标id
	protected long tenderId;
	// 投标记录
	protected BorrowTenderModel tender;
	// 投标用户
	protected User tenderUser;
	// 发标用户
	protected User borrowUser;
	// 还款计划
	private List<BorrowRepayment> repaymentList;
	// 协议模板
	protected Protocol protocol;
	// 操纵用户Id
	protected long userId;
	//还款方式
	protected String repayStyle;
	//开标日期
	protected String startTime;
	//还款日期
	protected String repayTime;
	//丙方公司名称
	protected String companyName;
	//丙方营业执照号
	protected String licenseNo;
	//丙方住所
	protected String address;
	//丙方法人代表
	protected String legalPerson;
	//借款总额
	protected String borrowAccount;
	//还款总额
	protected String repaymentAccount;
	//复审时间
	protected String reviewTime;
	/**
	 * 借款开始日~借款结束日间隔自然日
	 */
	protected long intervalDays;
	
    /**
     * 审核通过时间 
     */
	protected String vetifyTime;

	/**
	 * 乙方（借款人）
	 */
	protected MemberInfos memberInfos;
	
	protected PdfHelper pdf;
	// 引入数据map
	protected Map<String, Object> data = new HashMap<String, Object>();

	/**
	 * 业务核心处理方法
	 */
	@Override
	public void executer(long borrowId, Protocol protocol, long userId) {
		this.executer(borrowId, 0, protocol, userId);
	}

	/**
	 * 业务核心处理方法
	 */
	public void executer(long borrowId, long tenderId, Protocol protocol, long userId) {
		// 初始化基础参数
		logger.debug("初始化ProtocolBean");
		this.borrowService = (BorrowService) BeanUtil.getBean("borrowService");
		this.borrowTenderService = (BorrowTenderService) BeanUtil.getBean("borrowTenderService");
		this.borrowCollectionService = (BorrowCollectionService) BeanUtil.getBean("borrowCollectionService");
		this.verifyLogService = (VerifyLogService) BeanUtil.getBean("verifyLogService");
		this.userService = (UserService) BeanUtil.getBean("userService");
		this.borrowProtocolService = (BorrowProtocolService) BeanUtil.getBean("borrowProtocolService");
		this.borrowRepaymentService = (BorrowRepaymentService) BeanUtil.getBean("borrowRepaymentService");
		this.systemConfigService = (SystemConfigService) BeanUtil.getBean("systemConfigService");
		this.memberInfosDao = (MemberInfosDao) BeanUtil.getBean("memberInfosDao");
		String contextPath = ServletActionContext.getServletContext().getRealPath("/data/protocol/");
		this.inPdfName = contextPath + "/" + borrowId + "_" + System.currentTimeMillis() + ".pdf";
		this.pdf = PdfHelper.instance(inPdfName);
		this.borrowId = borrowId;
		this.borrow = BorrowModel.instance(borrowService.getBorrowById(borrowId));
		this.reviewTime=DateUtil.dateStr2(borrow.getReviewTime());
		this.downloadFileName = "借款协议"+reviewTime.substring(0, 4) +reviewTime.substring(5,7)+reviewTime.substring(8,10) + ".pdf";
		this.borrowUser = borrow.getUser();
		String realName =  borrow.getUser().getRealName();
		String cardId = borrow.getUser().getCardId();
		if(realName.length()==2){
			this.borrowUser.setRealName(realName.charAt(0)+"*");
		}else {
			this.borrowUser.setRealName(realName.charAt(0)+"**");
		}
		this.borrowUser.setCardId(cardId.substring(0,2) + "**************"  + cardId.substring(16, 18));
		this.protocol = protocol;
		this.tenderList = borrowTenderService.getTenderList(borrowId);
		this.repaymentList = borrowRepaymentService.getRepaymentByBorrowId(borrowId);
		this.borrowAccount=MoneyUtil.convert(borrow.getAccount() + "");
		this.repaymentAccount=MoneyUtil.convert(borrow.getRepaymentAccount()+"");
		this.userId = userId;
		this.repayTime=DateUtil.dateStr2(this.repaymentList.get(0).getRepaymentTime());
		if (borrow.getStyle() == BorrowStyle.STYLE_MONTHLY_INTEREST) {
			this.repayStyle = "每月还息到期还本";
		} else if (borrow.getStyle() == BorrowStyle.STYLE_ONETIME_REPAYMENT) {
			this.repayStyle = "一次性还款";
		} else {
			this.repayStyle = "按月分期付款";
		}
		if (tenderId != 0) {
			this.tenderId = tenderId;
			this.tender = BorrowTenderModel.instance(borrowTenderService.getTenderById(tenderId));
			this.tenderUser = this.tender.getUser();
			BorrowTender borrowTender = borrowTenderService.getBorrowTenderAmountByBorrowId(borrow.getId(),this.tender.getUser().getUserId());
			if(borrowTender!=null){
				this.tender.setAccount(borrowTender.getAccount());
				this.tender.setRepaymentAccount(borrowTender.getRepaymentAccount());
			}
		}
		this.vetifyTime = DateUtil.dateStr2(verifyLogService.findByType(borrowId, "borrow", 2).getTime());
		this.startTime=DateUtil.dateStr2(borrow.getPutStartTime());
		this.companyName=systemConfigService.findByNid("company_name").getValue();
		this.licenseNo=systemConfigService.findByNid("license_no").getValue();
		this.address=systemConfigService.findByNid("address").getValue();
		this.legalPerson=systemConfigService.findByNid("legal_person").getValue();
		this.memberInfos = memberInfosDao.findByUserId(borrowUser.getUserId());

		// 业务预处理
		prepare();
		// 下载协议校验
		validDownload();
		// 初始化参数
		initData();
        // 加盖印章
        createSignature();
		// 创建pdf逻辑
		createPdf();
	}

	@Override
	public abstract void prepare();

	@Override
	public void validDownload() {
		// 判断是否有模板
		if (this.protocol == null || StringUtil.isBlank(this.protocol.getContent())) {
			throw new BorrowException("读取协议模板出错！");
		}
		// 判断标是否存在
		if (this.borrow != null) {
			int status = this.borrow.getStatus();
			boolean isDown = status == 0 || status == 1 || status == 3 || status == 6 || status == 7 || status == 8;
			// 判断标是否状态异常
			if (!isDown) {
				throw new BorrowException("借款标状态异常！");
			}
		} else {
			throw new BorrowException("借款标不存在！");
		}
		// 判断用户是否存在
		if (userId == 0) {
			throw new BorrowException("用户信息异常！");
		}
	}

	@Override
	public void initData() {
		data.put("vetifyTimeYear", vetifyTime.substring(0,4)); //添加审核时间
		data.put("vetifyTimeMonth", vetifyTime.substring(5,7));
		data.put("vetifyTimeDay", vetifyTime.substring(8,10));
		data.put("reviewTime", reviewTime.substring(0, 4) + "年" +reviewTime.substring(5,7)+"月"+reviewTime.substring(8,10)+"日");
		data.put("reviewTimeYear", reviewTime.substring(0, 4));
		data.put("reviewTimeMonth", reviewTime.substring(5, 7));
		data.put("reviewTimeDay", reviewTime.substring(8, 10));
		data.put("borrowId", borrowId);
		data.put("borrow", this.borrow);
		data.put("repayStyle",this.repayStyle);
		data.put("startTimeYear",this.startTime.substring(0,4));
		data.put("startTimeMonth",this.startTime.substring(5, 7));
		data.put("startTimeDay",this.startTime.substring(8,10));
		data.put("repayTimeYear",this.repayTime.substring(0,4));
		data.put("repayTimeMonth",this.repayTime.substring(5,7));
		data.put("repayTimeDay",this.repayTime.substring(8,10));
		data.put("borrowAccount", MoneyUtil.convert(this.borrow.getAccount()+""));
		if (this.borrow.getVouchFirm() != null) {
			data.put("vouchFirmCache", UserUtils.getUserCacheByUserId(borrow.getVouchFirm().getUserId()));
		}
		data.put("borrowUser", this.borrowUser);
		data.put("borrowUserCache", UserUtils.getUserCacheByUserId(borrowUser.getUserId()));
		data.put("tenderList", tenderList);
		data.put("userId", userId);
		data.put("repaymentList", repaymentList);
		data.put("companyName",companyName);
		data.put("licenseNo",licenseNo);
		data.put("address",address);
		data.put("legalPerson",legalPerson);
		data.put("borrowAccount",borrowAccount);
		data.put("repaymentAccount",repaymentAccount);
		if (this.tenderId != 0) {
			data.put("tenderId", this.tenderId);
			data.put("tender", this.tender);
			data.put("tenderUser", this.tenderUser);
			double tenderAmount = this.borrowTenderService
					.hasTenderTotalPerBorrowByUserid(borrowId, tenderUser.getUserId());
			// 获取该用户投标总金额
			data.put("tenderAmount", tenderAmount);
		}
		data.put("memberInfos", memberInfos);
	}

	@Override
	public void createPdf() {
		boolean checkFile = false;
		File pdfFile = new File(inPdfName);
		try {
			if (!pdfFile.exists()) {
				pdfFile.mkdir();
			}
			String out = FreemarkerUtil.renderTemplate(protocol.getContent(), this.data);
			templateHtml(out, pdf);
			checkFile = true;
		} catch (Exception e) {
			logger.info("生成pdf出错");
			e.printStackTrace();
		}
		if (!checkFile) {
			throw new BorrowException("pdf生成的路径不存在...");
		}
		pdf.exportPdf();
	}

    private void createSignature(){
		UserCache userCache = (UserCache)data.get("borrowUserCache");
		String picPath = userCache.getZzjgPicPath(); // 公章路径
		if(StringUtil.isNotEmpty(picPath)) {
			pdf.setSignaturePath(picPath);
		}
    }

	/**
	 * 
	 * @param str
	 * @param pdf
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	private static String templateHtml(String str, PdfHelper pdf) throws IOException, DocumentException {
		final List<Element> pdfeleList = new ArrayList<Element>();
		ElementHandler elemH = new ElementHandler() {
			public void add(final Writable w) {
				if (w instanceof WritableElement) {
					pdfeleList.addAll(((WritableElement) w).elements());
				}
			}
		};
		InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(str.getBytes("UTF-8")), "UTF-8");
		XMLWorkerHelper.getInstance().parseXHtml(elemH, isr);
		List<Element> list = new ArrayList<Element>();
		for (Element ele : pdfeleList) {
			if (ele instanceof LineSeparator || ele instanceof WritableDirectElement) {
				continue;
			}
			list.add(ele);
		}
		pdf.addHtmlList(list);
		return "";
	}

	public String getInPdfName() {
		return inPdfName;
	}

	public void setInPdfName(String inPdfName) {
		this.inPdfName = inPdfName;
	}

	public String getDownloadFileName() {
		return downloadFileName;
	}

	public void setDownloadFileName(String downloadFileName) {
		this.downloadFileName = downloadFileName;
	}

}
